classdef HelperPLLLockDetector < matlab.System
    % HelperPLLLockDetector 用于检测锁相环（PLL）是否处于锁定状态
    %
    %   CCPLD = HelperPLLLockDetector 创建一个PLL锁定检测器对象。
    %
    %   Step方法语法：
    %
    %   [phlocko, phlockp] = step(CCPLD, integpval) 接收判探前积分结果
    %   integpval，根据判据输出宽锁定指示器phlocko与严锁定指示器phlockp。
    %   宽锁定判据反映PLL进入锁定状态的乐观条件，严锁定判据则表示更为严格的锁定区分。
    %
    %   HelperPLLLockDetector属性：
    %
    %   K1  ——    积分窗口的一阶低通滤波系数，详见表8.27
    %   K2  ——    判据门限因子
    %   Lp  ——    严锁定计数门限
    %   Lo  ——    宽锁定计数门限
    %   具体参考《Understanding GPS/GNSS》第8.13.2节相关内容。
    %
    %   参考文献：
    %   [1] Kaplan和Hegarty，《Understanding GPS/GNSS》，第8.13.2节

    properties(Nontunable)
        K1 = 0.0247   % 一阶低通滤波系数，见表8.27
        K2 = 1.5      % 判据门限因子
        Lp = 50       % 严锁定计数门限
        Lo = 240      % 宽锁定计数门限
    end

    properties(Access = private)
        LPFPLDI = 0   % 判探积分I支路一阶低通滤波输出
        LPFPLDQ = 0   % 判探积分Q支路一阶低通滤波输出
        Pcount1 = 0   % 严锁定计数器
        Pcount2 = 0   % 宽锁定计数器
    end

    methods(Access = public)
        function obj = HelperPLLLockDetector(config)
            obj.K1 = config.module.pllLockDetector.K1;
            obj.K2 = config.module.pllLockDetector.K2;
            obj.Lp = config.module.pllLockDetector.Lp;
            obj.Lo = config.module.pllLockDetector.Lo;
        end
    end

    methods(Access = protected)
        function [phlocko, phlockp] = stepImpl(obj, integpval)
            % 算法实现：根据相干积分输出，判定PLL锁定状态
            % 严锁定与宽锁定分别反映严格与宽松的锁定判据
            % 严锁定：判据达到连续计数Lp后设定
            % 宽锁定：判据达到连续计数Lo后解除锁定

            % 一阶低通滤波处理两分支积分值
            obj.LPFPLDI = (1 - obj.K1) * obj.LPFPLDI + obj.K1 * abs(real(integpval));
            obj.LPFPLDQ = (1 - obj.K1) * obj.LPFPLDQ + obj.K1 * abs(imag(integpval));
            phlockp = false; % 严锁定指示
            phlocko = false; % 宽锁定指示

            if obj.LPFPLDI > obj.LPFPLDQ * obj.K2
                phlocko = true; % 宽锁定状态
                obj.Pcount2 = 0;
                if obj.Pcount1 > obj.Lp
                    phlockp = true; % 严锁定状态
                else
                    obj.Pcount1 = obj.Pcount1 + 1; % 增加严锁定计数
                end
            else
                phlockp = false;
                obj.Pcount1 = 0;
                if obj.Pcount2 > obj.Lo
                    phlocko = false; % 宽锁定解除
                else
                    obj.Pcount2 = obj.Pcount2 + 1; % 增加宽锁定计数
                end
            end
        end

        function resetImpl(obj)
            % 重置滤波器及计数器状态
            obj.LPFPLDI = 0;
            obj.LPFPLDQ = 0;
            obj.Pcount1 = 0;
            obj.Pcount2 = 0;
        end 
    end
end
